﻿using AKBGame.Object;
using AKBGame.Util;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AKBGame
{
    public partial class AddSongForm : Form
    {
        public delegate void SongUpdateHandler(object sender, SongUpdateEventArgs e);
        public event SongUpdateHandler SongUpdated;

        public List<string> FileList = new List<string>();
        public List<SongIDMapping> SongIDMappingList { get; set; }
        public List<ClothIDMapping> ClothIDMappingList { get; set; }

        public AddSongForm()
        {
            InitializeComponent();

            GetSongIDMapping();
            FillSongComboBox(SongIDMappingList);

            GetClothIDMapping();
            FillClothComboBox(ClothIDMappingList);
            
            if (!Directory.Exists(@"Data\SongData"))
            {
                Directory.CreateDirectory(@"Data\SongData");
            }

            FileList = Directory.GetFiles(@"Data\SongData", "*.*")
                                 .Select(path => Path.GetFileName(path)).ToList();

            FillSongFileListView(FileList);
        }

        private void FillSongComboBox(List<SongIDMapping> songIDMappingList)
        {
            comboBoxSongName.DataSource = songIDMappingList;
            comboBoxSongName.DisplayMember = "SongName";
            comboBoxSongName.ValueMember = "ID";
        }

        private void FillClothComboBox(List<ClothIDMapping> clothIDMappingList)
        {
            string[] clothNameArray = clothIDMappingList.Select(o => o.Cloth).Distinct().ToArray();
            comboBoxClothBonus1.Items.AddRange(clothNameArray);
            comboBoxClothBonus2.Items.AddRange(clothNameArray);
            comboBoxClothBonus3.Items.AddRange(clothNameArray);
            comboBoxClothBonus4.Items.AddRange(clothNameArray);
        }

        private void FillSongFileListView(List<string> fileList)
        {
            listViewSongFileList.Items.Clear();

            foreach (string file in fileList)
            {
                string[] row = { file };

                var listViewItem = new ListViewItem(row);
                listViewSongFileList.Items.Add(listViewItem);
            }

            listViewSongFileList.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
        }

        private List<RhythmData> ReadRhythmDataFromFile(string path, ref string mappingName)
        {
            List<RhythmData> rhythmDataList = new List<RhythmData>();

            try
            {
                byte[] byteArray = File.ReadAllBytes(@"Data\SongData\" + path);
                string fileString = Encoding.UTF8.GetString(byteArray);

                int dataIndex = fileString.IndexOf("new_rhythm_data");
                mappingName = fileString.Substring(dataIndex, "new_rhythm_data_xxx_xx".Length);

                int dataContentIndex = fileString.LastIndexOf(mappingName);
                string dataContentString = fileString.Remove(0, dataContentIndex);

                string[] dataContentArray = dataContentString.Split(new string[] { "\0", "\r\n" }, StringSplitOptions.None).Where(o => o.Count(x => x == ' ') == 3).ToArray();

                foreach (string dataContent in dataContentArray.Take(dataContentArray.Length - 1))
                {
                    string[] rhythmDataArray = dataContent.Split(new char[] { ' ' });

                    RhythmData rhythmData = new RhythmData();
                    rhythmData.Time = float.Parse(rhythmDataArray[0]);
                    rhythmData.PositionType = int.Parse(rhythmDataArray[1]);
                    rhythmData.TapType = int.Parse(rhythmDataArray[2]);
                    rhythmData.ColorType = int.Parse(rhythmDataArray[3]);
                    rhythmDataList.Add(rhythmData);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("The file is invalid!");
            }

            return rhythmDataList;
        }

        private void buttonAddSong_Click(object sender, EventArgs e)
        {
            try
            {
                if (listViewSongFileList.SelectedItems.Count < 1)
                {
                    MessageBox.Show("Please select file!");
                }
                else
                {
                    var selectedItem = listViewSongFileList.SelectedItems[0];
                    string mappingName = "";
                    List<RhythmData> rhythmDataList = ReadRhythmDataFromFile(selectedItem.SubItems[0].Text, ref mappingName);

                    Song song = new Song();
                    song.ID = (int)comboBoxSongName.SelectedValue;
                    song.SongName = comboBoxSongName.Text;
                    song.RhythmDataList = rhythmDataList;
                    song.RhythmDataMappingName = mappingName;
                    song.HighScore = 0;
                    song.ClothBonusIDList = new List<int>();

                    if (!string.IsNullOrEmpty(comboBoxClothBonus1.Text))
                        song.ClothBonusIDList.Add(ClothIDMappingList.First(o => o.Cloth == comboBoxClothBonus1.Text).ID);
                    if (!string.IsNullOrEmpty(comboBoxClothBonus2.Text))
                        song.ClothBonusIDList.Add(ClothIDMappingList.First(o => o.Cloth == comboBoxClothBonus2.Text).ID);
                    if (!string.IsNullOrEmpty(comboBoxClothBonus3.Text))
                        song.ClothBonusIDList.Add(ClothIDMappingList.First(o => o.Cloth == comboBoxClothBonus3.Text).ID);
                    if (!string.IsNullOrEmpty(comboBoxClothBonus4.Text))
                        song.ClothBonusIDList.Add(ClothIDMappingList.First(o => o.Cloth == comboBoxClothBonus4.Text).ID);

                    SongUpdateEventArgs args = new SongUpdateEventArgs(song);
                    SongUpdated(this, args);
                    this.Dispose();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void GetSongIDMapping()
        {
            byte[] songStream = TextFileHelper.LoadByte(@"Data\SongIDMapping.txt");
            string songJSON = GZipStreamHelper.UncompressString(Convert.ToBase64String(songStream));

            SongIDMappingList = new List<SongIDMapping>();

            SongJSON.RootObject songList = JsonConvert.DeserializeObject<SongJSON.RootObject>(songJSON);
            foreach (SongJSON.Datum songJSONObject in songList.data)
            {
                SongIDMapping songIDMapping = new SongIDMapping();
                songIDMapping.ID = songJSONObject.ID;
                songIDMapping.SongName = songJSONObject.JP;
                SongIDMappingList.Add(songIDMapping);
            }
        }

        public class SongUpdateEventArgs : System.EventArgs
        {
            private Song song;

            public SongUpdateEventArgs(Song song)
            {
                this.song = song;
            }

            public Song Song
            {
                get
                {
                    return song;
                }
            }
        }

        private void listViewSongFileList_Click(object sender, EventArgs e)
        {
            SelectMappingFile();
        }

        private void SelectMappingFile()
        {
            var selectedItem = listViewSongFileList.SelectedItems[0];
            textBoxFileName.Text = selectedItem.SubItems[0].Text;

            try
            {
                byte[] byteArray = File.ReadAllBytes(@"Data\SongData\" + textBoxFileName.Text);
                string fileString = Encoding.UTF8.GetString(byteArray);

                int dataIndex = fileString.IndexOf("new_rhythm_data");
                int songID = int.Parse(fileString.Substring(dataIndex, "new_rhythm_data_xxx".Length).Remove(0, "new_rhythm_data_".Length));
                string mappingName = fileString.Substring(dataIndex, "new_rhythm_data_xxx_xx".Length);

                textBoxMappingName.Text = mappingName;
                comboBoxSongName.SelectedValue = songID;
            }

            catch (Exception ex)
            {

            }
        }

        private void GetClothIDMapping()
        {
            byte[] clothStream = TextFileHelper.LoadByte(@"Data\ClothIDMapping.txt");
            string clothJSON = GZipStreamHelper.UncompressString(Convert.ToBase64String(clothStream));

            ClothIDMappingList = new List<ClothIDMapping>();

            ClothIDMappingJSON.RootObject clothList = JsonConvert.DeserializeObject<ClothIDMappingJSON.RootObject>(clothJSON);
            foreach (ClothIDMappingJSON.Datum clothJSONObject in clothList.data)
            {
                ClothIDMapping clothIDMapping = new ClothIDMapping();
                clothIDMapping.ID = clothJSONObject.ID;
                clothIDMapping.Cloth = clothJSONObject.JP;
                ClothIDMappingList.Add(clothIDMapping);
            }
        }

        private void listViewSongFileList_KeyUp(object sender, KeyEventArgs e)
        {
            SelectMappingFile();
        }
    }
}
